package com.dns.server.secondary;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;

import com.dns.message.DNS_Message;
import com.dns.util.Constants;

public class RequestHandlerThread extends Thread {

	DatagramPacket requestPacket;
	DNS_Message	requestMsg;
	
	public 
	
	RequestHandlerThread(DatagramPacket pkt)
	{		
		requestPacket = pkt;
	}
	
	public void run( )
	{
		constructRequestMessageFromPacket();
		try {
			processRequestMessage();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void constructRequestMessageFromPacket()
	{
		ByteArrayInputStream byteInputStream =null;
		ObjectInputStream objectInputStream = null;
		byteInputStream = new ByteArrayInputStream(requestPacket.getData());
		
		try{			
			objectInputStream = new ObjectInputStream(byteInputStream);
			requestMsg = (DNS_Message)objectInputStream.readObject();
			SecondaryServer.printMessage(requestMsg);
		}
		catch (IOException e) {
			System.out.println(this.getClass().getName()+" : Exception while de-serializing the DNS_Message object");
			e.printStackTrace();
		}
		catch (ClassNotFoundException e) {
			System.out.println(this.getClass().getName()+" : Exception while creating the deserialized DNS_Message object");
			e.printStackTrace();
		}		
		
	}
	
	public  void processRequestMessage() throws IOException
	{
		String msgSource = requestMsg.getSource();
		if(msgSource.equals(Constants.CLIENT))
			processClientMessage();
		else if(msgSource.equals(Constants.PRIMARY))
			processPrimaryServerMessage();
		
	}
	
	private void processClientMessage() throws IOException
	{
		if(requestMsg.getMsgType() == Constants.MSG_UPDATE)
		{
			//System.out.println("MSG RCVD: UPDATE");

			String clientIP = requestMsg.getClientAddress();
			int clientPort = requestMsg.getClientPort();
			
			String domain = requestMsg.getDomainName();
			String ip = requestMsg.getIp_address();
			int ttl = requestMsg.getTtl();

			DNS_Message primaryServerUpdateMsg = new DNS_Message();
			primaryServerUpdateMsg.setSource(Constants.SECONDARY);
			primaryServerUpdateMsg.setClientAddress(Configurations.myIPddress);
			primaryServerUpdateMsg.setClientPort(Configurations.portForRequests);
			primaryServerUpdateMsg.setDomainName(domain);
			primaryServerUpdateMsg.setIp_address(ip);
			primaryServerUpdateMsg.setMsgType(Constants.MSG_UPDATE);			
			primaryServerUpdateMsg.setTtl(ttl);

			DNS_Message clientResponseMsg = new DNS_Message();
			clientResponseMsg.setSource(Constants.SECONDARY);			
			clientResponseMsg.setClientAddress(Configurations.myIPddress);
			clientResponseMsg.setClientPort(Configurations.portForRequests);
			clientResponseMsg.setDomainName(domain);
			clientResponseMsg.setIp_address(ip);
			clientResponseMsg.setMsgType(Constants.MSG_RESPONSE);

			
			if(0 == DomainDataHandler.updateDomain(domain, ip, ttl))
			{
				primaryServerUpdateMsg.setResult(Constants.SUCCESS);
				SecondaryServer.sendMessage(primaryServerUpdateMsg);
				clientResponseMsg.setResult(Constants.SUCCESS);
				SecondaryServer.sendMessageToClient(clientIP, clientPort, clientResponseMsg);
			}
			else
			{
				clientResponseMsg.setResult(Constants.FAILURE);
				SecondaryServer.sendMessageToClient(clientIP, clientPort, clientResponseMsg);
			}
			
		}
		
	}
	
	private void processPrimaryServerMessage()
	{
		if(requestMsg.getMsgType() == Constants.MSG_INQUIRY)
		{
			//System.out.println("MSG RCVD: INQUIRY");
			String domain = null;
			String ip = null;
			domain = requestMsg.getDomainName();
		    ip = requestMsg.getIp_address();

			requestMsg.setMsgType(Constants.MSG_RESPONSE);
			requestMsg.setSource(Constants.SECONDARY);
			
			if(!(domain == null) && (ip == null))
			{
				//System.out.println("DNS INQUIRY");
				String replyIp = DomainDataHandler.getIPFromDomain(domain);				
				if(!(replyIp == null))
				{					
					requestMsg.setIp_address(replyIp);
					requestMsg.setTtl(DomainDataHandler.getTTLFromDomain(domain));
					requestMsg.setResult(Constants.SUCCESS);
					//System.out.println("DNS INQUIRY - SUCCESS");
				}
				else
				{					
					requestMsg.setResult(Constants.FAILURE);
					//System.out.println("DNS INQUIRY - FAILED");
				}
			}
			else if((domain == null) && !(ip == null))
			{
				System.out.println("MSG RCVD: REVERSE DNS INQUIRY");
				String replyDomain = DomainDataHandler.getDomainFromIP(ip);				
				if(!(replyDomain == null))
				{
					requestMsg.setDomainName(replyDomain);
					requestMsg.setTtl(DomainDataHandler.getTTLFromDomain(replyDomain));
					requestMsg.setResult(Constants.SUCCESS);
					//System.out.println("REVERSE DNS INQUIRY - SUCCESS");					
				}
				else
				{
					requestMsg.setResult(Constants.FAILURE);
					//System.out.println("REVERSE DNS INQUIRY - FAILED");					
				}
			}
			else
			{
				requestMsg.setResult(Constants.FAILURE);
				//System.out.println("INVALID Query: Both DOMAIN NAME And IP Are Present");
			}			
		}
		else
		{
			requestMsg.setResult(Constants.FAILURE);
			//System.out.println("INVALIDE QUERY TYPE");			
		}
		
		SecondaryServer.sendMessage(requestMsg);
		//System.out.println("MSG SENT: RESPONSE");	
	}
	
}
